package service

import (
	"context"
	"fmt"
	"sync"
	"time"

	"go.uber.org/zap"

	"yanxue_ai_go/pkg/common/logger"
	"yanxue_ai_go/pkg/common/redis"
)

// ServiceInfo 服务信息
type ServiceInfo struct {
	Name     string            `json:"name"`
	Address  string            `json:"address"`
	Port     int               `json:"port"`
	Health   string            `json:"health"` // healthy, unhealthy, unknown
	LastSeen time.Time         `json:"last_seen"`
	Metadata map[string]string `json:"metadata"`
}

// ServiceRegistry 服务注册中心
type ServiceRegistry struct {
	services map[string]*ServiceInfo
	mutex    sync.RWMutex
}

// NewServiceRegistry 创建服务注册中心
func NewServiceRegistry() *ServiceRegistry {
	registry := &ServiceRegistry{
		services: make(map[string]*ServiceInfo),
	}

	// 初始化默认服务
	registry.initDefaultServices()

	// 启动健康检查
	go registry.startHealthCheck()

	return registry
}

// initDefaultServices 初始化默认服务配置
func (sr *ServiceRegistry) initDefaultServices() {
	defaultServices := []*ServiceInfo{
		{
			Name:     "agent",
			Address:  "agent", // Docker内部网络地址
			Port:     8081,
			Health:   "unknown",
			LastSeen: time.Now(),
			Metadata: map[string]string{"type": "ai-agent"},
		},
		{
			Name:     "mcp",
			Address:  "mcp",
			Port:     8082,
			Health:   "unknown",
			LastSeen: time.Now(),
			Metadata: map[string]string{"type": "model-context-protocol"},
		},
		{
			Name:     "rag",
			Address:  "rag",
			Port:     8083,
			Health:   "unknown",
			LastSeen: time.Now(),
			Metadata: map[string]string{"type": "retrieval-augmented-generation"},
		},
	}

	sr.mutex.Lock()
	for _, service := range defaultServices {
		sr.services[service.Name] = service
	}
	sr.mutex.Unlock()
}

// RegisterService 注册服务
func (sr *ServiceRegistry) RegisterService(service *ServiceInfo) {
	sr.mutex.Lock()
	defer sr.mutex.Unlock()

	service.LastSeen = time.Now()
	sr.services[service.Name] = service

	logger.Logger.Info("Service registered",
		zap.String("service", service.Name),
		zap.String("address", fmt.Sprintf("%s:%d", service.Address, service.Port)))
}

// UnregisterService 注销服务
func (sr *ServiceRegistry) UnregisterService(serviceName string) {
	sr.mutex.Lock()
	defer sr.mutex.Unlock()

	delete(sr.services, serviceName)

	logger.Logger.Info("Service unregistered", zap.String("service", serviceName))
}

// GetService 获取服务信息
func (sr *ServiceRegistry) GetService(serviceName string) (*ServiceInfo, bool) {
	sr.mutex.RLock()
	defer sr.mutex.RUnlock()

	service, exists := sr.services[serviceName]
	return service, exists
}

// GetAllServices 获取所有服务
func (sr *ServiceRegistry) GetAllServices() map[string]*ServiceInfo {
	sr.mutex.RLock()
	defer sr.mutex.RUnlock()

	result := make(map[string]*ServiceInfo)
	for name, service := range sr.services {
		result[name] = service
	}
	return result
}

// GetHealthyServices 获取健康的服务
func (sr *ServiceRegistry) GetHealthyServices() map[string]*ServiceInfo {
	sr.mutex.RLock()
	defer sr.mutex.RUnlock()

	result := make(map[string]*ServiceInfo)
	for name, service := range sr.services {
		if service.Health == "healthy" {
			result[name] = service
		}
	}
	return result
}

// startHealthCheck 启动健康检查
func (sr *ServiceRegistry) startHealthCheck() {
	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			sr.performHealthCheck()
		}
	}
}

// performHealthCheck 执行健康检查
func (sr *ServiceRegistry) performHealthCheck() {
	sr.mutex.Lock()
	defer sr.mutex.Unlock()

	for name, service := range sr.services {
		go func(serviceName string, serviceInfo *ServiceInfo) {
			health := sr.checkServiceHealth(serviceInfo)

			sr.mutex.Lock()
			if currentService, exists := sr.services[serviceName]; exists {
				currentService.Health = health
				currentService.LastSeen = time.Now()
			}
			sr.mutex.Unlock()

			logger.Logger.Debug("Health check completed",
				zap.String("service", serviceName),
				zap.String("health", health))
		}(name, service)
	}
}

// checkServiceHealth 检查单个服务健康状态
func (sr *ServiceRegistry) checkServiceHealth(service *ServiceInfo) string {
	// 这里可以实现HTTP健康检查
	// 暂时使用简单的逻辑
	return "healthy" // 简化实现
}

// SaveToRedis 保存服务信息到Redis
func (sr *ServiceRegistry) SaveToRedis(ctx context.Context) error {
	sr.mutex.RLock()
	defer sr.mutex.RUnlock()

	for name, service := range sr.services {
		key := fmt.Sprintf("service_registry:%s", name)
		if err := redis.Set(ctx, key, service, 5*time.Minute); err != nil {
			logger.Logger.Error("Failed to save service to Redis",
				zap.String("service", name),
				zap.Error(err))
			return err
		}
	}

	return nil
}

// LoadFromRedis 从Redis加载服务信息
func (sr *ServiceRegistry) LoadFromRedis(ctx context.Context) error {
	// 这里可以实现从Redis加载服务信息的逻辑
	// 暂时跳过实现
	return nil
}
